//--------------------------------------------------------------------------------
// This file is a portion of the D2D1Renderer.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Mirco Timmermann
//
//--------------------------------------------------------------------------------
#include "Rect.h"

#include "Circle.h"
#include "Point2f.h"


Rect::Rect(void) {
	_x = 0.0f;
	_y = 0.0f;

	_width = 1.0f;
	_height = 1.0f;
}

Rect::Rect(float width, float height) {
	_x = 0.0f;
	_y = 0.0f;

	_width = width;
	_height = height;
}

Rect::Rect(float x, float y, float width, float height) {
	_x = x;
	_y = y;

	_width = width;
	_height = height;
}

Rect::~Rect(void) {

}

float Rect::Bottom(void) {
	return _y + _height;
}

float Rect::Top(void) {
	return _y;
}

float Rect::Left(void) {
	return _x;
}

float Rect::Right(void) {
	return _x + _width;
}

Point2f Rect::GetCenter() {
	return Point2f(_x + _width/2, _y + _height/2);
}

/*
* (union)
* makes of two rectangles a new rectangle that includes both rectangles.
*/
Rect Rect::operator + (const Rect &r) const {
	float left = r._x;
	if(this->_x < left) left = this->_x;

	float top = r._y;
	if(this->_y < top) top = this->_y;

	float right = r._x + r._width;
	if((this->_x + this->_width) > right) right = (this->_x + this->_width);
	
	float bottom = r._y + r._height;
	if((this->_y + this->_height) > bottom) bottom = (this->_y + this->_height);

	return Rect(left, top, right - left, bottom - top);
}

Rect Rect::operator += (const Rect &r) const {
	Rect rect = operator+(r);
	return rect;
}


/*
* checks if the point is inside the rectangle.
* +--------+      
* |      x |      
* |        |      
* |        |
* +--------+
*/
bool Rect::Intersect(Point2f point) {
	return (point.x > this->Left() && point.x < this->Right() && point.y > this->Top() && point.y < this->Bottom());
}

/*
* checks if the rectangle cuts the rectangle.
* +--------+      
* |        |      
* |        |      
* |      +-+----+
* +------+-+    |
*        |      |
*        +------+
*/
bool Rect::Intersect(Rect rectangle) {
	if(rectangle.Bottom() < this->Top())		return false;
	if(rectangle.Top() > this->Bottom())		return false;
	if(rectangle.Right() < this->Left())		return false;
	if(rectangle.Left() > this->Right())		return false;

	return true;
}

/*
* checks if the rectangle cuts the rectangle.
*  +------------+     _____ 
*  | +--------+ |    /     \
*  | |        | |   |   +   |
*  | |        | |    \_____/
*  | +--------+ |
*  +------------+
* Recttangle._width += radius   (makes circle to point)
* Recttangle._height += radius  (makes circle to point)
*  
*/
bool Rect::Intersect(Circle circle) {
	Rect rectangle(this->_x - circle.radius, this->_y - circle.radius, this->_width + (circle.radius*2), this->_height + (circle.radius*2));
	return (circle.x > rectangle.Left() && circle.x < rectangle.Right() && circle.y > rectangle.Top() && circle.y < rectangle.Bottom());
}

////////////

/*
* When the width or height are minus the rectangle will be transformed.
--------(+)     (+)--------
| -width |       | +width |
| -height|  ->   | +height|
|        |       |        |
----------       ----------
*
*
*/
void Rect::MakeHomogen() {
	if(_width < 0) {
		_x += _width;
		_width *= -1;
	}
	if(_height < 0) {
		_y += _height;
		_height *= -1;
	}
}

bool Rect::operator < (const Point2f &p) {
	return (p.x > Left() && p.x < Right() && p.y > Top() && p.y < Bottom());
}

bool Rect::operator > (const Point2f &p) {
	return !operator<(p);
}

bool Rect::operator <= (const Point2f &p) {
	return (p.x >= Left() && p.x <= Right() && p.y >= Top() && p.y <= Bottom());
}

bool Rect::operator >= (const Point2f &p) {
	return !operator<(p);
}